// 8 : input length				//here should never replace !!
// $compress_code : 



`define WIDTH	8
`define PP_NUM  (WIDTH/2+1)
`define RESULT_WIDTH (`WIDTH*2)
module booth2(
	      input logic [`WIDTH-1:0] i_a,
	      input logic [`WIDTH-1:0] i_b,
	      input logic 	       i_sign
	      );

   wire [`WIDTH-1+1:0] 	  a = {i_sign & i_a[`WIDTH], i_a}; // sign extension for one bit
   wire [`WIDTH-1+2:0] 	  b = {{2{i_sign & i_b[`WIDTH]}}, i_b}; // sign extension for 2 bits
   wire [`WIDTH-1+3:0] 	  b_ext = {b, 1'b0};		    // the 0 after the LSb used for booth2 recoding

   logic signed [`WIDTH:0] pp[`PP_NUM-1:0]; // one bit more than original input i_a
   logic 		  E[`PP_NUM-1:0]; // infact, the last is not needed
   logic 		  S[`PP_NUM-1:0]; // the last is not needed

   //logic [3:0] cols[31:0];
   // logic signed [2:0] 	  booth_array[8:0];	//0, +-1, +-2
   //    
   //logic signed [31:0] 	  result;	//for 16x16
   logic signed [`RESULT_WIDTH-1:0] result;
   

   // ==================== generate PP, S, E ====================
   generate
      genvar 			    i;
      for(i=0;i<`PP_NUM;i++)
	begin : mul_pp
	   Mfxu_mul_smul_igen #(`WIDTH) Fxu_igen_mul
	    (
	     .igen_val (pp[i]),	// the PP
	     .igen_ci(S[i]),
	     .E(E[i]),

	     .u(a),		// the multiplicand 
	     .vx(b_ext[i*2+2:i*2]) // 
	     );
	end // block: mul_pp
   endgenerate

   
   // ==================== PPs compress ====================
   logic [`RESULT_WIDTH-1:0] final_pp0, final_pp1;
   logic S1_1_1,S1_1_0,S1_3_1,S1_4_2,S1_5_2,S1_4_1,S1_6_2,S1_7_2,S1_7_3,S1_8_2,S1_7_1,S1_9_2,S1_9_3,S1_10_2,S1_10_3,S1_11_2,S1_11_3,S1_12_2,S1_12_3,S1_13_2,S1_12_1,S1_14_2,S1_15_1,S1_16_Carry_0;
logic S2_0_0,S2_2_1,S2_2_0,S2_4_2,S2_5_1,S2_6_2,S2_7_2,S2_8_2,S2_7_1,S2_9_2,S2_10_2,S2_9_1,S2_11_2,S2_10_1,S2_12_2,S2_11_1,S2_13_1,S2_12_1,S2_14_1,S2_15_1,S2_16_Carry_0;
logic S3_0_0,S3_1_0,S3_3_1,S3_3_0,S3_5_1,S3_6_1,S3_7_2,S3_8_1,S3_9_2,S3_10_2,S3_11_2,S3_12_2,S3_13_1,S3_14_1,S3_15_1,S3_16_Carry_0;
// ==================== Stage1 ====================
HA ha1 (S1_1_1,S1_0_0,pp[0][0],S[0]);
assign S1_1_0 = pp[0][1];
FA fa1 (S1_3_1,S1_2_0,pp[0][2],pp[1][0],S[1]);
HA ha2 (S1_4_2,S1_3_0,pp[0][3],pp[1][1]);
FA fa2 (S1_5_2,S1_4_0,pp[0][4],pp[1][2],pp[2][0]);
assign S1_4_1 = S[2];
FA fa3 (S1_6_2,S1_5_0,pp[0][5],pp[1][3],pp[2][1]);
FA fa4 (S1_7_2,S1_6_0,pp[0][6],pp[1][4],pp[2][2]);
HA ha3 (S1_7_3,S1_6_1,pp[3][0],S[3]);
FA fa5 (S1_8_2,S1_7_0,pp[0][7],pp[1][5],pp[2][3]);
assign S1_7_1 = pp[3][1];
FA fa6 (S1_9_2,S1_8_0,pp[0][8],pp[1][6],pp[2][4]);
HA ha4 (S1_9_3,S1_8_1,pp[3][2],pp[4][0]);
FA fa7 (S1_10_2,S1_9_0,{~E[0]},pp[1][7],pp[2][5]);
HA ha5 (S1_10_3,S1_9_1,pp[3][3],pp[4][1]);
FA fa8 (S1_11_2,S1_10_0,{~E[0]},pp[1][8],pp[2][6]);
HA ha6 (S1_11_3,S1_10_1,pp[3][4],pp[4][2]);
FA fa9 (S1_12_2,S1_11_0,E[0],E[1],pp[2][7]);
HA ha7 (S1_12_3,S1_11_1,pp[3][5],pp[4][3]);
FA fa10 (S1_13_2,S1_12_0,1'b1,pp[2][8],pp[3][6]);
assign S1_12_1 = pp[4][4];
FA fa11 (S1_14_2,S1_13_0,E[2],pp[3][7],pp[4][5]);
FA fa12 (S1_15_1,S1_14_0,1'b1,pp[3][8],pp[4][6]);
HA ha8 (S1_16_Carry_0,S1_15_0,E[3],pp[4][7]);
// ==================== Stage2 ====================
assign S2_0_0 = S1_0_0;
HA ha9 (S2_2_1,S2_1_0,S1_1_0,S1_1_1);
assign S2_2_0 = S1_2_0;
HA ha10 (S2_4_2,S2_3_0,S1_3_0,S1_3_1);
FA fa13 (S2_5_1,S2_4_0,S1_4_0,S1_4_1,S1_4_2);
HA ha11 (S2_6_2,S2_5_0,S1_5_0,S1_5_2);
FA fa14 (S2_7_2,S2_6_0,S1_6_0,S1_6_1,S1_6_2);
FA fa15 (S2_8_2,S2_7_0,S1_7_0,S1_7_1,S1_7_2);
assign S2_7_1 = S1_7_3;
FA fa16 (S2_9_2,S2_8_0,S1_8_0,S1_8_1,S1_8_2);
FA fa17 (S2_10_2,S2_9_0,S1_9_0,S1_9_1,S1_9_2);
assign S2_9_1 = S1_9_3;
FA fa18 (S2_11_2,S2_10_0,S1_10_0,S1_10_1,S1_10_2);
assign S2_10_1 = S1_10_3;
FA fa19 (S2_12_2,S2_11_0,S1_11_0,S1_11_1,S1_11_2);
assign S2_11_1 = S1_11_3;
FA fa20 (S2_13_1,S2_12_0,S1_12_0,S1_12_1,S1_12_2);
assign S2_12_1 = S1_12_3;
HA ha12 (S2_14_1,S2_13_0,S1_13_0,S1_13_2);
HA ha13 (S2_15_1,S2_14_0,S1_14_0,S1_14_2);
HA ha14 (S2_16_Carry_0,S2_15_0,S1_15_0,S1_15_1);
// ==================== Stage3 ====================
assign S3_0_0 = S2_0_0;
assign S3_1_0 = S2_1_0;
HA ha15 (S3_3_1,S3_2_0,S2_2_0,S2_2_1);
assign S3_3_0 = S2_3_0;
HA ha16 (S3_5_1,S3_4_0,S2_4_0,S2_4_2);
HA ha17 (S3_6_1,S3_5_0,S2_5_0,S2_5_1);
HA ha18 (S3_7_2,S3_6_0,S2_6_0,S2_6_2);
FA fa21 (S3_8_1,S3_7_0,S2_7_0,S2_7_1,S2_7_2);
HA ha19 (S3_9_2,S3_8_0,S2_8_0,S2_8_2);
FA fa22 (S3_10_2,S3_9_0,S2_9_0,S2_9_1,S2_9_2);
FA fa23 (S3_11_2,S3_10_0,S2_10_0,S2_10_1,S2_10_2);
FA fa24 (S3_12_2,S3_11_0,S2_11_0,S2_11_1,S2_11_2);
FA fa25 (S3_13_1,S3_12_0,S2_12_0,S2_12_1,S2_12_2);
HA ha20 (S3_14_1,S3_13_0,S2_13_0,S2_13_1);
HA ha21 (S3_15_1,S3_14_0,S2_14_0,S2_14_1);
HA ha22 (S3_16_Carry_0,S3_15_0,S2_15_0,S2_15_1);
// ==================== Final 2 PPs ====================
assign final_pp0 = {S3_15_0,S3_14_0,S3_13_0,S3_12_0,S3_11_0,S3_10_0,S3_9_0,S3_8_0,S3_7_0,S3_6_0,S3_5_0,S3_4_0,S3_3_0,S3_2_0,S3_1_0,S3_0_0};
assign final_pp1 = {S3_15_1,S3_14_1,S3_13_1,S3_12_2,S3_11_2,S3_10_2,S3_9_2,S3_8_1,S3_7_2,S3_6_1,S3_5_1,1'b0,S3_3_1,1'b0,1'b0,1'b0};


   

   
endmodule // booth2

   
   
   
   